<?php
class Query {
/// definition and constructor ///
	var $mDsn = null;
	var $mDb = null;
	var $mRes = null;
	var $mError = null;
	
	var $mTable = false;
	var $mField = array("*");
	var $mWhere = array();
	var $mGroup = array();
	var $mOrder = array();

	var $mRecord = array();

	var $mSql = null;
	var $mSqlSelect  = "SELECT ::FIELD:: FROM ::TABLE:: ::WHERE:: ::GROUP:: ::ORDER::";
	var $mSqlInsert  = "INSERT INTO ::TABLE:: SET ::DATA::";
	var $mSqlReplace = "REPLACE INTO ::TABLE:: SET ::DATA::";
	var $mSqlUpdate  = "UPDATE ::TABLE:: SET ::DATA:: ::WHERE::";
	var $mSqlDelete  = "DELETE FROM ::TABLE:: ::WHERE::";
	
	function Query($dsn=null) {
		$this->connect($dsn);
	}

/// connect functions ///
	function connect($dsn=null) {
		if (isset($dsn) && strlen($dsn) > 0) { $this->cfgConnect($dsn); }
		else { $this->cfgConnect(__DSN_DEFAULT); }
		$rDsn = parse_url($this->mDsn);
		if (!$this->mDb) { $this->mDb = mysql_connect($rDsn["host"], $rDsn["user"], $rDsn["pass"]); }
		mysql_select_db(str_replace("/", "", $rDsn["path"]), $this->mDb);
		mysql_query("SET NAMES '{$rDsn['scheme']}'", $this->mDb);
	}

	function disconnect() {
		mysql_close($this->mDb);
		$this->mDb = false;
	}

/// configure function ///
	function cfgConnect($dsn) {
		$this->mDsn = $dsn;
	}

	function cfgTable($tablename) {
		$this->mTable = (string)$tablename;
	}

	function cfgField($fields) {
		if (is_array($fields) && 0 < sizeof($fields)) {
			$this->mField = array_unique($fields);
		}
		elseif (is_string($fields) && 0 < strlen($fields)) {
			$this->mField = array_unique(explode(",", trim($fields, " ,")));
		}
		else {
			$this->mField = null;
		}
	}

	function cfgWhere($conditions) {
		if (is_array($conditions) && 0 < sizeof($conditions)) {
			$this->mWhere = $conditions;
		}
		elseif (is_string($conditions) && 0 < strlen($conditions)) {
			$this->mWhere = array($conditions);
		}
		else {
			$this->mWhere = null;
		}
	}

	function cfgGroup($groupby) {
		if (is_array($groupby) && 0 < sizeof($groupby)) {
			$this->mGroup = $groupby;
		}
		elseif (is_string($groupby) && 0 < strlen($groupby)) {
			$this->mGroup = explode(",", $groupby);
		}
		else {
			$this->mGroup = null;
		}
	}

	function cfgOrder($orderby) {
		if (is_array($orderby) && 0 < sizeof($orderby)) {
			$this->mOrder = $orderby;
		}
		elseif (is_string($orderby) && 0 < strlen($orderby)) {
			$this->mOrder = explode(",", $orderby);
		}
		else {
			$this->mOrder = null;
		}
	}

/// execute functions ///
	function loadOne() {
		$this->_fetchSql("Select");
//@ echo $this->mSql . "<br />\n";
		if ($this->mRes = mysql_query($this->mSql . " LIMIT 1", $this->mDb)) {
			$tmp_r = mysql_fetch_assoc($this->mRes);
			if ($tmp_r) {
				$this->mRecord = array_merge($this->mRecord, $tmp_r);
			}
			mysql_free_result($this->mRes);
		}
	}

	function loadQuery($sql) {
		$this->mSql = $sql;
//@ echo $this->mSql . "<br />\n";
		$this->mRes = mysql_query($this->mSql, $this->mDb);
		if ($this->mRes) {
			return true;
		}
		else {
			return false;
		}
	}

	function insert() {
		$this->_fetchSql("Insert");
//@ echo $this->mSql . "<br />\n";
		if (mysql_query($this->mSql, $this->mDb)) {
			return mysql_insert_id($this->mDb);
		}
		else {
			return false;
		}
	}

	function replace() {
		$this->_fetchSql("Replace");
//@ echo $this->mSql . "<br />\n";
		if (mysql_query($this->mSql, $this->mDb)) {
			return true;
		}
		else {
			return false;
		}
	}

	function update() {
		$this->_fetchSql("Update");
//@ echo $this->mSql . "<br />\n";
		if (mysql_query($this->mSql, $this->mDb)) {
			return true;
		}
		else {
			return false;
		}
	}

	function delete() {
		if (!$this->mWhere) { return false; } // prevent delete all
		$this->_fetchSql("Delete");
//@ echo $this->mSql . "<br />\n";
		if (mysql_query($this->mSql, $this->mDb)) {
			return true;
		}
		else {
			return false;
		}
	}

/// list control functions ///
	function nextRecord($save=true) {
		if ($tmp_r = @mysql_fetch_assoc($this->mRes)) {
			if ($save) {
				$this->mRecord = array_merge($this->mRecord, $tmp_r);
				return true;
			}
			else{
				return $tmp_r;
			}
		}
		else return false;
	}

/// get functions ///
	function get($path) {
		if (is_array($path)) {
			$sTarget = '$this->mRecord[' . implode("][", $path) . ']';
			eval('$tmp = (isset('.$sTarget.') ? '.$sTarget.' : false);');
			return $tmp;
		}
		else{
			return (isset($this->mRecord[$path]) ? $this->mRecord[$path] : false);
		}
	}

	function getCfg($cfgname) {
		$value = null;
		@eval('$value = $this->cfg' . $cfgname . ';');
		return $value;
	}

	function getData() {
		return $this->mRecord;
	}

	function getError() {
		return $this->mError;
	}

	function getAffectedRows() {
		return mysql_affected_rows($this->mDb);
	}

/// set functions ///
	function set($path, $val=null) {
		if (is_array($path)) {
			eval('$target =& $this->mRecord[\'' . implode("']['", $path) . '\'];');
		}
		elseif (null == $path) {
			$target =& $this->mRecord;
		}
		else{
			$target =& $this->mRecord[$path];
		}
		if (is_array($target) && is_array($val)) {
			$target = array_merge($target, $val);
		}
		else{
			$target = $val;
		}
	}

	function free() {
		@mysql_free_result($this->mRes);
		$this->mRecord = array();
	}

/// core functions ///
	function _fetchSql($action) {
		switch ($action) {
		case "Select":
			$this->mSql = str_replace(
				array("::FIELD::", "::TABLE::", "::WHERE::", "::GROUP::" ,"::ORDER::"),
				array(
					($this->mField ? implode(", ", $this->mField) : "*"),
					($this->mTable ? $this->mTable : ""),
					($this->mWhere ? "WHERE (" . implode(") AND (", $this->mWhere) . ")" : ""),
					($this->mGroup ? "GROUP BY " . implode(", ", $this->mGroup) : ""),
					($this->mOrder ? "ORDER BY " . implode(", ", $this->mOrder) : "")
				),
				$this->mSqlSelect
			);
			break;
		case "Insert":
			$rSqlData = array();
			foreach ($this->mField as $val) {
				$val = explode(" ", trim($val));
				if (!isset($this->mRecord[$val[sizeof($val)-1]])) { continue; }
				$rSqlData[] = $val[0] . "=" . ("_AUTO_" === $this->mRecord[$val[sizeof($val)-1]] ? "NULL" : "'" . addslashes($this->mRecord[$val[sizeof($val)-1]]) . "'");
			}
			$this->mSql = str_replace(
				array("::TABLE::", "::DATA::"),
				array(
					($this->mTable ? $this->mTable : ""),
					implode(", ", $rSqlData)
				),
				$this->mSqlInsert
			);
			break;
		case "Replace":
			$rSqlData = array();
			foreach ($this->mField as $val) {
				$val = explode(" ", trim($val));
				if (!isset($this->mRecord[$val[sizeof($val)-1]])) { continue; }
				$rSqlData[] = $val[0] . "=" . ("_AUTO_" === $this->mRecord[$val[sizeof($val)-1]] ? "NULL" : "'" . addslashes($this->mRecord[$val[sizeof($val)-1]]) . "'");

			}
			$this->mSql = str_replace(
				array("::TABLE::", "::DATA::"),
				array(
					($this->mTable ? $this->mTable : ""),
					implode(", ", $rSqlData)
				),
				$this->mSqlReplace
			);
			break;
		case "Update":
			$rSqlData = array();
			foreach ($this->mField as $val) {
				$val = explode(" ", trim($val));
				if (!isset($this->mRecord[$val[sizeof($val)-1]])) { continue; }
				$rSqlData[] = $val[0] . "=" . ("_AUTO_" === $this->mRecord[$val[sizeof($val)-1]] ? "NULL" : "'" . addslashes($this->mRecord[$val[sizeof($val)-1]]) . "'");

			}
			$this->mSql = str_replace(
				array("::TABLE::", "::DATA::", "::WHERE::"),
				array(
					($this->mTable ? $this->mTable : ""),
					implode(", ", $rSqlData),
					($this->mWhere ? "WHERE (" . implode(") AND (", $this->mWhere) . ")" : ""),
				),
				$this->mSqlUpdate
			);
			break;
		case "Delete":
			$this->mSql = str_replace(
				array("::TABLE::", "::WHERE::"),
				array(
					($this->mTable ? $this->mTable : ""),
					($this->mWhere ? "WHERE (" . implode(") AND (", $this->mWhere) . ")" : ""),
				),
				$this->mSqlDelete
			);
			break;
		default:
			break;
		}
//@ echo $this->mSql."<br />\n";
		return $this->mSql;
	}
	
} /// end class Query.
?>
